home *** CD-ROM | disk | FTP | other *** search
- ;* TIMER.ASM
- ;*
- ;* TempoTimer
- ;*
- ;* $Id: timer.asm,v 1.2 1997/01/16 18:41:59 pekangas Exp $
- ;*
- ;* Copyright 1996,1997 Housemarque Inc.
- ;*
- ;* This file is part of the MIDAS Sound System, and may only be
- ;* used, modified and distributed under the terms of the MIDAS
- ;* Sound System license, LICENSE.TXT. By continuing to use,
- ;* modify or distribute this file you indicate that you have
- ;* read the license and understand and accept it fully.
- ;*
-
-
- IDEAL
- P386
- JUMPS
-
- INCLUDE "lang.inc"
- INCLUDE "mglobals.inc"
- INCLUDE "errors.inc"
- INCLUDE "timer.inc"
- IFNDEF NOEMS
- INCLUDE "ems.inc"
- ENDIF
- INCLUDE "sdevice.inc"
-
- ;TIMERBORDERS=1
-
- MAXPLAYERS = 16 ; maximum number of music players
-
- NTPRATE = 100 ; non-tempoPolling SoundDevice
- ; interrupt rate if not synchronized
- ; to screen (in Hz)
-
- IFDEF __32__
- FRAMETIME = 950
- ELSE
- FRAMETIME = 965 ; Time between two interrupts is 96.5%
- ; of total frame time - the interrupt comes
- ; somewhat _before_ the Vertical Retrace
- ; actually starts.
- ENDIF
-
-
- ENUM tmrStates \ ; timer state
- tmrSystem, \ ; system timer
- tmrPlayer, \ ; music player timer
- tmrScreen ; Vertical Retrace timer
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Macro: SetBorder color
- ;*
- ;* Description: Sets the border color if TIMERBORDERS is defined
- ;*
- ;* Input: color border color
- ;*
- ;* Destroys: none
- ;*
- ;\***************************************************************************/
-
- MACRO SetBorder color
- IFDEF TIMERBORDERS
- push _dx _ax
- mov dx,03DAh
- in al,dx
- mov dx,03C0h
- mov al,31h
- out dx,al
- mov al,color
- out dx,al
- pop _ax _dx
- ENDIF
- ENDM
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Macro: WaitNextVR
- ;*
- ;* Description: Waits for next Vertical Retrace
- ;*
- ;\***************************************************************************/
-
- MACRO WaitNextVR
- LOCAL w1, w2
-
- mov dx,03DAh
- w1: in al,dx ; wait for a non-retrace period
- test al,8
- jnz w1
-
- w2: in al,dx
- test al,8 ; wait for retrace
- jz w2
- ENDM
-
-
-
-
- DATASEG
-
-
- D_farptr systemTimer ; pointer to system timer routine
- sysTmrCount DD ? ; system timer counter
-
- playCount DD ? ; player timer counter
- playTmrCount DD ? ; initial value for player timer count
- D_ptr sdev ; pointer to Sound Device
-
- musicPlayers DD MAXPLAYERS DUP(?) ; music player routines
-
- D_int playSD ; 1 if sound should be played
- D_int plTimer ; 1 if player-timer is active
- D_int plError ; music playing error code
- D_int plCallMP ; call music player?
-
- scrCount DD ? ; Retrace timer counter
- scrTmrCount DD ? ; initial value for VR timer counter
- scrPVCount DD ? ; timer count for time before Retrace
- D_ptr preVR ; pre-VR function
- D_ptr immVR ; immVR()
- D_ptr inVR ; inVR()
- D_int scrSync ; 1 if timer is synchronized to screen
- D_int scrTimer ; 1 if screen-timer is active
- D_int scrPlayer ; synchronize player to screen?
-
- D_int tmrState ; timer state
-
- D_int sysTimer ; system timer active?
-
- IFNDEF __PASCAL__
- D_int tmrActive ; running in timer interrupt? (global)
- ENDIF
-
-
-
-
- CODESEG
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: setCount
- ;*
- ;* Description: Set timer count and restart timer
- ;*
- ;* Input: bx timer count
- ;*
- ;* Destroys: al
- ;*
- ;\***************************************************************************/
-
- PROC NOLANGUAGE setCount NEAR ; set timer counter and restart
-
- mov al,30h ; counter mode 0 - interrupt on
- out 43h,al ; terminal count
- mov al,bl
- out 40h,al ; set timer count and restart timer
- mov al,bh
- out 40h,al
-
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: nextTimer
- ;*
- ;* Description: Prepare for next timer interrupt
- ;*
- ;* Destroys: eax, ebx
- ;*
- ;\***************************************************************************/
-
- PROC NOLANGUAGE nextTimer NEAR
-
- cmp [scrSync],1 ; is timer synchronized to screen?
- jne @@noscr
-
- cmp [playSD],1 ; should sound be played?
- jne @@scr
-
- mov ebx,[playCount] ; player timer count
- or ebx,ebx ; negative
- jns @@nos1
- mov ebx,10 ; make sure count is not negative
- mov [playCount],10
- jmp @@setpl
- @@nos1:
- cmp ebx,[scrCount] ; will player timer come before scr?
- jl @@setpl
-
- @@scr: mov ebx,[scrCount] ; screen timer count
- or ebx,ebx ; negative?
- jns @@nos2
- mov ebx,10 ; make sure count is not negative
- mov [scrCount],10
- @@nos2:
- mov [tmrState],tmrScreen ; next interrupt will be screen timer
- call setCount ; set count and restart timer
- jmp @@done
-
-
- @@setpl:
- mov [tmrState],tmrPlayer ; next interrupt will be player
- call setCount ; set count and restart
- jmp @@done
-
-
- @@noscr:
- cmp [playSD],1 ; should sound be played?
- jne @@sys
-
- mov [tmrState],tmrPlayer
- mov ebx,[playCount] ; player timer count
- or ebx,ebx ; negative?
- jns @@1
-
- mov ebx,10 ; make sure count is not negative
- mov [playCount],10
-
- @@1: call setCount
- jmp @@done
-
-
- @@sys: ; system timer only
- mov [tmrState],tmrSystem ; next int is system timer
- xor _bx,_bx
- call setCount ; set system timer count
-
- @@done:
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: timer
- ;*
- ;* Description: timer interrupt handler
- ;*
- ;\***************************************************************************/
-
- PROC NOLANGUAGE timer ; timer interrupt
-
- pushad
- push ds es fs gs
-
- SetBorder 15
-
- mov ax,DGROUP
- mov ds,ax ; set valid values to segment
- mov es,ax ; registers
-
- mov [tmrActive],1 ; in timer interrupt
-
- cmp [tmrState],tmrScreen ; screen timer interrupt?
- je @@scrtmr
- cmp [tmrState],tmrSystem ; system timer only?
- je @@systmr
- cmp [tmrState],tmrPlayer ; player timer?
- je @@plrtmr
- jmp @@systmr ; do _something_
-
-
- @@scrtmr:
- cli ; no interrupts here!
-
- SetBorder 14
-
- cmp [scrTimer],1 ; is screen timer already active?
- jne @@scrnot
-
- ; screen timer already active - PANIC!
-
- mov eax,[scrCount]
- add eax,[scrPVCount]
- sub [playCount],eax ; update player timer counter
- add [sysTmrCount],eax ; update system timer counter
-
- mov eax,[scrTmrCount] ; reset screen timer counter
- mov [scrCount],eax
-
- call nextTimer ; next timer interrupt
-
- mov al,20h ; send End Of Interrupt
- out 20h,al
- sti ; enable interrupts
- jmp @@done ; stop processing this interrupt
-
-
- @@scrnot:
- cmp [scrSync],1 ; should timer be synchronized to
- jne @@chksys ; screen?
-
- mov [scrTimer],1 ; screen-timer is now active
-
- mov dx,03DAh
- @@wnvr: in al,dx ; wait until we are _not_ in a
- test al,8 ; retrace (just to make sure...)
- jnz @@wnvr
-
- cmp [preVR],0
- je @@npvr ; call preVR() if pointer is not
- call [_ptr preVR] LANG ; NULL
- @@npvr:
-
- SetBorder 1
- mov eax,[scrCount]
- add eax,[scrPVCount] ; update timer counters
- add [sysTmrCount],eax
-
- cmp [scrPlayer],1 ; synchronize player to screen?
- je @@syncpl
- sub [playCount],eax ; no, update count
- jmp @@scd
-
- @@syncpl:
- mov eax,[playTmrCount] ; synchronize player
- mov [playCount],eax
-
- @@scd:
- mov eax,[scrTmrCount] ; reset screen-interrupt count
- mov [scrCount],eax
-
- mov dx,03DAh
- @@wvr: in al,dx ; wait for the retrace
- test al,8
- jz @@wvr
-
- cmp [immVR],0
- je @@nivr ; call immVR() if pointer is not
- call [_ptr immVR] LANG ; NULL
-
- @@nivr:
- SetBorder 2
-
- call nextTimer ; next timer iterrupt
-
- mov [scrTimer],0 ; screen-timer (almost) finished
-
- SetBorder 4
-
- sti ; enable interrupts now
-
- mov al,20h ; send End Of Interrupt to Interrupt
- out 20h,al ; Controller
-
-
- cmp [inVR],0
- je @@nvr ; call inVR() if pointer is not NULL
- call [_ptr inVR] LANG
-
- @@nvr:
- SetBorder 0
- mov [scrTimer],0
- jmp @@chksys ; check if system timer should be
- ; called
-
-
-
-
-
- @@plrtmr:
- ;SetBorder 7
- cmp [plTimer],1 ; is player timer already active?
- jne @@plnot ; if not, it's OK to continue
-
- ; player timer already active - PANIC!
-
- mov eax,[playCount] ; previous player timer count
- sub [scrCount],eax ; update screen timer count
- add [sysTmrCount],eax ; and system timer count
- mov eax,[playTmrCount] ; reset player timer count
- mov [playCount],eax
- call nextTimer ; next timer interrupt (hopefully
- ; not player anymore...)
- sti ; enable interrupts
- mov al,20h ; send End Of Interrupt
- out 20h,al
- jmp @@done ; quit interrupt - no playing until
- ; the previous player interrupt has
- ; finished
-
- @@plnot:
- mov [plTimer],1 ; player timer is active
- mov eax,[playCount] ; player timer count
- or eax,eax
- js @@pn1
- sub [scrCount],eax ; update screen timer count
- add [sysTmrCount],eax ; increase system timer count
- @@pn1:
- cmp [scrPlayer],1 ; synchronize player to screen?
- je @@pspl
- mov ebx,[playTmrCount] ; new player timer count
- mov [playCount],ebx ; set player timer count to counter
- jmp @@pnt
- @@pspl:
- mov [playCount],0FFFFh ; make sure that next interrupt will
- @@pnt: ; be screen, not timer
-
- call nextTimer ; next timer interrupt
-
- sti ; enable interrupts
- mov al,20h ; send End Of Interrupt to Interrupt
- out 20h,al ; Controller
-
- cmp [playSD],1 ; should music be played?
- je @@playmus
-
- mov [plTimer],0 ; player timer not active
- jmp @@chksys ; call system timer if appropriate
-
- @@playmus:
- cmp [plError],0 ; error during playing?
- jne @@pl1
-
- mov edi,[playTmrCount] ; store player timer count
-
- ; Start playing loop: (usually updates DMA position)
- LOADPTR es,_si,[sdev]
- call [_essi+SoundDevice.StartPlay] LANG
- test _ax,_ax
- jnz @@plerr
-
- SetBorder 14
-
- IFNDEF NOEMS
- cmp [mUseEMS],1 ; is EMS used?
- jne @@play
- call emsSave LANG ; save EMS mappings
- test _ax,_ax
- jnz @@plerr
-
- call emsSafe LANG ; set EMS "safe"-flag on
- test _ax,_ax
- jnz @@plerr
- ENDIF
-
- @@play:
- SetBorder 15
- ; Update Sound Device registers / mix data:
- LOADPTR es,_si,[sdev]
- IFDEF __16__
- call [_essi+SoundDevice.Play] LANG, seg plCallMP offset plCallMP
- ELSE
- call [_essi+SoundDevice.Play] LANG, ptr_to plCallMP
- ENDIF
- SetBorder 2
- test _ax,_ax
- jnz @@plerr
-
- cmp [plCallMP],1 ; should music player be called?
- jne @@noplay
-
- lea _si,[musicPlayers] ; point ds:si to music players
-
- @@playmusic:
- cmp [_ptr _si],0 ; is current music player zero?
- je @@nothispl ; if is, do not play
-
- call [_ptr _si] LANG ; play music
- test _ax,_ax
- jnz @@plerr
-
- @@nothispl:
- add _si,4
- cmp _si,(offset musicPlayers) + 4*MAXPLAYERS
- jb @@playmusic
-
- LOADPTR es,_si,[sdev]
- cmp [_essi+SoundDevice.tempoPoll],0 ; poll again if
- je @@play ; tempoPoll flag is zero
-
- @@noplay:
- IFNDEF NOEMS
- cmp [mUseEMS],1
- jne @@nems1
- SetBorder 14
- call emsStopSafe LANG
- test _ax,_ax
- jnz @@plerr
-
- call emsRestore LANG
- test _ax,_ax
- jnz @@plerr
- ENDIF
-
- @@nems1:
- SetBorder 0
-
- LOADPTR es,_si,[sdev]
- cmp [_essi+SoundDevice.tempoPoll],1 ; no need to change
- jne @@pl1 ; timer rate if tempoPoll is zero.
-
- cmp [playTmrCount],edi ; has player timer count been changed?
- je @@pl1
-
- mov ebx,[playTmrCount]
- mov [playCount],ebx ; set new player timer count
- cmp [tmrState],tmrPlayer ; would next interrupt be player?
- jne @@pl1
- call nextTimer ; if so, set new count
-
- jmp @@pl1
-
- @@plerr:
- mov [plError],_ax ; playing error
-
- @@pl1: mov [plTimer],0 ; player timer finished
-
-
- @@chksys: ; check system timer
- sti
- cmp [sysTmrCount],10000h ; should system timer be called?
- jb @@done
-
- mov eax,[sysTmrCount]
- sub eax,10000h ; substract 65536 from system timer
- or eax,eax ; count. Is the result negative?
- jns @@stcok ; (SHOULD not be)
- xor eax,eax ; negative - set to zero
- @@stcok:
- mov [sysTmrCount],eax ; new timer count
- IFDEF __16__
- pushf
- ELSE
- pushfd
- ENDIF
- call [_farptr systemTimer] ; call system timer
- jmp @@chksys
-
-
-
- @@systmr: ; system timer only
- sti
- xor _bx,_bx ; set new timer count and restart
- call setCount
- IFDEF __16__
- pushf
- ELSE
- pushfd
- ENDIF
- call [_farptr systemTimer] ; call system timer
-
-
- @@done:
- mov [tmrActive],0 ; not in timer interrupt
- SetBorder 0
- pop gs fs es ds ; restore registers
- popad
- nop ; avoid the popad-bug...
- IFDEF __16__
- iret
- ELSE
- iretd
- ENDIF
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrGetScrSync(unsigned *scrSync);
- ;*
- ;* Description: Calculates the screen synchronization value for timer
- ;*
- ;* Input: unsigned *scrSync pointer to screen synchronization
- ;* value
- ;*
- ;* Returns: MIDAS error code.
- ;* Screen syncronization value used with tmrSyncScr() is stored
- ;* in *scrSync.
- ;*
- ;\***************************************************************************/
-
- PROC tmrGetScrSync _funct PscrSync : _ptr
- LOCAL tmrVal : _int
-
- cli ; disable interrupts for maximum
- ; accuracy
- @@read:
- xor _ax,_ax
- WaitNextVR ; wait for next Vertical Retrace
-
- mov al,36h
- out 43h,al
- xor al,al ; reset the timer
- out 40h,al
- out 40h,al
-
-
- WaitNextVR ; wait for next Vertical Retrace
-
- xor al,al
- out 43h,al
- in al,40h
- mov ah,al
- in al,40h ; read timer count - time between
- xchg al,ah ; two Vertical Retraces
- neg ax
- mov [tmrVal],_ax
-
- xor _ax,_ax
- WaitNextVR ; wait for next Vertical Retrace
-
- mov al,36h
- out 43h,al
- xor al,al ; reset timer again
- out 40h,al
- out 40h,al
-
-
- WaitNextVR ; wait...
-
- xor al,al
- out 43h,al
- in al,40h
- mov ah,al ; and read the timer count again
- in al,40h
- xchg al,ah
- neg ax
-
- mov _dx,_ax
-
- sub _dx,[tmrVal]
- cmp _dx,2 ; If the difference between the two
- jg @@read ; values read was >2, read again.
- cmp _dx,-2
- jl @@read
-
- sti ; enable interrupts
-
- LOADPTR es,_bx,[PscrSync] ; store time in *scrSync
- mov [_esbx],_ax
-
- xor _ax,_ax ; success
-
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrInit(void);
- ;*
- ;* Description: Initializes TempoTimer.
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC tmrInit _funct
-
- mov [tmrState],tmrSystem ; only system timer now
- mov [playSD],0
- mov [scrSync],0
- mov [plTimer],0
- mov [scrTimer],0
- mov [sysTmrCount],0
- mov [sysTimer],0
- mov [plError],0
-
- IFDEF __32__
- push es
- ENDIF
-
- mov ax,3508h
- int 21h
- IFDEF __16__
- mov [word systemTimer],bx ; save system timer interrupt
- mov [word systemTimer+2],es
- ELSE
- mov [dword systemTimer],ebx ; save system timer interrupt
- mov [word systemTimer+4],es
- ENDIF
-
- IFDEF __32__
- pop es
- ENDIF
-
- push ds
- ; mov ax,seg timer
- mov ax,cs
- mov ds,ax ; set new timer interrupt
- mov _dx,offset timer
- mov ax,2508h
- int 21h
- pop ds
-
- xor _bx,_bx ; set timer count and restart
- call setCount
-
- SetBorder 2
-
- xor _ax,_ax ; success
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrClose(void);
- ;*
- ;* Description: Uninitializes TempoTimer. MUST be called if and ONLY if
- ;* tmrInit() has been called.
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC tmrClose _funct
-
- mov al,36h ; DOS default timer mode
- out 43h,al
- xor al,al ; set timer count to 65536 - 18.2Hz
- out 40h,al ; (DOS default)
- out 40h,al
-
- push ds
- mov ax,2508h
- lds _dx,[systemTimer] ; restore system timer interrupt
- int 21h
- pop ds
-
- mov al,36h ; DOS default timer mode
- out 43h,al
- xor al,al ; set timer again for safety
- out 40h,al
- out 40h,al
-
- xor _ax,_ax ; success
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrPlaySD(SoundDevice *SD);
- ;*
- ;* Description: Starts playing sound with a Sound Device ie. calling its
- ;* Play() function in the update rate, which is set to
- ;* 50Hz.
- ;*
- ;* Input: SoundDevice *SD Sound Device that will be used
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC tmrPlaySD _funct SD : _ptr
- USES _di
-
- mov eax,[SD] ; save Sound Device pointer
- mov [sdev],eax
-
- lea _di,[musicPlayers]
- mov ax,ds
- mov es,ax ; reset music player pointers
- xor al,al ; to NULL - no music players
- mov _cx,MAXPLAYERS * PTRSIZE
- cld
- rep stosb
-
- cli ; disable interrupts for a while
-
- LOADPTR es,_di,[sdev]
- cmp [_esdi+SoundDevice.tempoPoll],1
- je @@tempo ; use tempo-polling?
-
- cmp [scrSync],0 ; synchronize to screen?
- je @@noss
- mov eax,25 ; yes - synchronize also player
- mul [scrTmrCount] ; interrupt count = 1/4 of screen
- mov ebx,100 ; interrupt count (player interrupt
- div ebx ; will come somewhat after Vertical
- mov ebx,eax ; Retrace end)
- mov [scrPlayer],1 ; synchronize player to screen
- jmp @@1
-
- @@noss:
- mov ebx,1193180/NTPRATE ; set polling rate to NTPRATE Hz
- ; (default 100Hz)
- mov [scrPlayer],0 ; don't synchronize to screen
- jmp @@1
- @@tempo:
- mov ebx,1193180/50 ; tempo-polling - set update rate to
- mov [scrPlayer],0 ; 50Hz, don't synchronize to screen
- @@1:
- mov [playTmrCount],ebx ; player timer count
- mov [playCount],ebx
- mov [playSD],1 ; playing sound
- mov [plTimer],0 ; player timer not active
- mov [plError],0 ; no error during playing
-
- cmp [tmrState],tmrSystem ; is only system timer running?
- jne @@noset ; if not, don't set count and restart
-
- mov [tmrState],tmrPlayer ; next interrupt will be player int
- call setCount
- mov [sysTmrCount],0
-
- @@noset:
- sti
-
- SetBorder 3
-
- xor _ax,_ax ; success
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrStopSD(void);
- ;*
- ;* Description: Stops playing sound with the Sound Device.
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC tmrStopSD _funct
-
- cli
-
- mov [playSD],0
- cmp [scrSync],0 ; is timer synchronized to screen?
- jne @@noset ; if is, don't force system timer
-
- mov [tmrState],tmrSystem ; only system timer now
- xor _bx,_bx
- call setCount
-
- @@noset:
- sti
-
- xor _ax,_ax ; success
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrPlayMusic(void *play, int *playerNum);
- ;*
- ;* Description: Starts playing music with the timer.
- ;*
- ;* Input: void *play Pointer to music playing function.
- ;* Must return MIDAS error codes
- ;* int *playerNum Pointer to player number, used
- ;* for stopping music
- ;*
- ;* Returns: MIDAS error code. Player number is written to *playerNum.
- ;*
- ;* Notes: There can be a maximum of 16 music players active at the
- ;* same time.
- ;*
- ;\****************************************************************************/
-
- PROC tmrPlayMusic _funct play : _ptr, playerNum : _ptr
-
- mov eax,[play]
- lea _bx,[musicPlayers] ; point bx to music player ptrs
- xor _cx,_cx ; cx = player number
-
- ; Find free music player slot or return errOutOfResources if none
- ; left:
- @@search:
- cmp [_ptr _bx],0 ; is current player slot free?
- je @@free
- add _bx,PTRSIZE
- inc _cx ; next player number
- cmp _cx,MAXPLAYERS ; past the limit?
- jb @@search
-
- mov _ax,errOutOfResources
- jmp @@err
-
- @@free:
- mov [_bx],eax ; free player number found (in cx)
- LOADPTR es,_bx,[playerNum] ; write player number to
- mov [_esbx],_cx ; *playerNum
-
- xor _ax,_ax
- jmp @@done
-
- @@err:
- ERROR ID_tmrPlayMusic
-
- @@done:
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrStopMusic(int playerNum);
- ;*
- ;* Description: Stops playing music with the timer.
- ;*
- ;* Input: int playerNum Number of player to be stopped.
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC tmrStopMusic _funct playerNum : _int
-
- mov _bx,[playerNum] ; write NULL to player pointer to
- shl _bx,2 ; mark it free
- mov [_ptr musicPlayers+_bx],0
-
- xor _ax,_ax
-
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrSyncScr(unsigned sync, void (*preVR)(),
- ;* void (*immVR)(), void (*inVR)());
- ;*
- ;* Description: Synchronizes the timer to screen refresh.
- ;*
- ;* Input: unsigned sync Screen synchronization value returned
- ;* by tmrGetScrSync().
- ;* void (*preVR)() Pointer to the routine that will be
- ;* called BEFORE Vertical Retrace
- ;* void (*immVR)() Pointer to the routine that will be
- ;* called immediately after Vertical
- ;* Retrace starts
- ;* void (*inVR)() Pointer to the routine that will be
- ;* called some time during Vertical
- ;* Retrace
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;* Notes: preVR() and immVR() functions must be as short as possible
- ;* and do nothing else than update counters or set some VGA
- ;* registers to avoid timer synchronization problems. inVR()
- ;* can take a longer time and can be used for, for example,
- ;* setting the palette.
- ;*
- ;* Remember to use the correct calling convention for the xxVR()
- ;* routines! (pascal for Pascal programs, cdecl otherwise).
- ;*
- ;\***************************************************************************/
-
- PROC tmrSyncScr _funct sync : _int, PpreVR : _ptr, PimmVR : _ptr, \
- PinVR : _ptr
- USES _si
-
- cli ; make sure we won't be disturbed...
-
- mov eax,[PpreVR]
- mov [preVR],eax
- mov eax,[PimmVR] ; store function pointers
- mov [immVR],eax
- mov eax,[PinVR]
- mov [inVR],eax
-
- mov [scrSync],1 ; synchronize to screen
- mov [scrTimer],0 ; screen timer is not active
-
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,FRAMETIME
- mul [sync] ; time between two screen interrupts
- mov _bx,1000 ; is FRAMETIME/10 % of total frame
- div _bx ; time
-
- shr eax,1
- mov [scrCount],eax ; screen timer counter
- mov [scrTmrCount],eax
- mov ebx,eax
-
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,[sync]
- shr eax,1 ; scrPVCount = timer count between
- sub eax,ebx ; interrupt and start of Vertical
- mov [scrPVCount],eax ; Retrace
-
- mov [tmrState],tmrScreen ; next timer interrupt is screen timer
- WaitNextVR ; wait for next retrace
- call setCount ; set count and restart timer
-
- sti
-
-
- cmp [playSD],0 ; is sound being played?
- je @@nomsync
-
- LOADPTR es,_si,[sdev] ; do not synchronize player
- cmp [_essi+SoundDevice.tempoPoll],1 ; interrupt to screen if
- je @@nomsync ; tempo-polling is used
-
- mov eax,25
- mul [scrTmrCount] ; interrupt count = 1/4 of screen
- mov ebx,100 ; interrupt count (player interrupt
- div ebx ; will come somewhat after Vertical
- mov ebx,eax ; Retrace end)
- mov [scrPlayer],1 ; synchronize player to screen
-
- mov [playTmrCount],ebx ; player timer count
- mov [playCount],ebx
-
- @@nomsync:
- xor _ax,_ax ; success
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrStopScrSync(void);
- ;*
- ;* Description: Stops synchronizing the timer to the screen.
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC tmrStopScrSync _funct
-
- cli
-
- cmp [scrPlayer],1 ; is player being synchronized to
- jne @@nospl ; screen?
-
- mov ebx,1193180/NTPRATE ; set polling rate to NTPRATE Hz
- ; (default 100Hz)
- mov [playTmrCount],ebx ; player timer count
- mov [playCount],ebx
- mov [scrPlayer],0 ; don't synchronize to screen
-
- @@nospl:
- mov [scrSync],0 ; no screen synchronization
- mov [scrTimer],0 ; screen timer is not active
- call nextTimer ; set timer count and restart
-
- sti
-
- xor _ax,_ax ; success
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int tmrSetUpdRate(unsigned updRate);
- ;*
- ;* Description: Sets the timer update rate, ie. the rate at which the music
- ;* playing routine is called
- ;*
- ;* Input: unsigned updRate updating rate, in 100*Hz (5000=50Hz)
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC tmrSetUpdRate _funct updRate : _int
-
- LOADPTR es,_bx,[sdev]
- cmp [_esbx+SoundDevice.tempoPoll],0 ; don't change rate
- je @@done ; if tempoPoll == 0
-
- mov eax,119318000
- xor edx,edx ; eax = new timer count
- IFDEF __16__
- xor ebx,ebx
- ENDIF
- mov _bx,[updRate]
- div ebx
- mov [playTmrCount],eax
-
- @@done:
- xor _ax,_ax ; success
- ret
- ENDP
-
-
- ;* $Log: timer.asm,v $
- ;* Revision 1.2 1997/01/16 18:41:59 pekangas
- ;* Changed copyright messages to Housemarque
- ;*
- ;* Revision 1.1 1996/05/22 20:49:33 pekangas
- ;* Initial revision
- ;*
-
- END